Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature request] More intelligent compression #116

Closed
rupert-madden-abbott opened this issue Jun 12, 2011 · 111 comments
Closed

[feature request] More intelligent compression #116

rupert-madden-abbott opened this issue Jun 12, 2011 · 111 comments
Labels
enhancement New feature or request

Comments

@rupert-madden-abbott
Copy link

It would be great if SASS output could be configured to more intelligently compress output. Here are some examples:

# Combine name-spaced selectors
# SASS                             # Preferred Output                 # Current Output
body {                             body{border:3px solid #ccc;}       body{border-width:3px;border-color:#ccc;border-style:solid;}
  border: {
    width: 3px;
    color: #ccc;
    style: solid
    }
}

# Combine multiple declarations
# SASS                             # Preferred Output                 # Current Output
body { border: solid #ccc; }       body{border:3px solid #ccc;}       body{border:solid #ccc;}
body { border-width: 3px; }                                           body{border-width:3px;}

# SASS                             # Preferred Output                 # Current Output
body { color: #ccc; }              body{color:#ccc;cursor:pointer;}   body{color:#ccc;}
body { cursor: pointer; }                                             body{cursor:pointer;}          

# Ignore overridden declarations
# SASS                             # Preferred Output                 # Current Output
body { border: 2px solid #400; }   body{border:3px solid #ccc;}       body{border:2px solid #400;}
body { border: 3px solid #ccc; }                                      body{border:3px solid #ccc;}

This would allow you to more expressively organise stylesheets and partials without sacrificing on output length. For example, you could have color, typography and layout partials which, when compiled, gave the same output as if they had been written all mixed together.

There maybe gotchas with doing this due to the cascading nature of stylesheets and this effectively changes the ordering of declarations. However, I can't immediately think of specifics and the first case at least does not seem to be problematic.

This should also only apply when the compressed output option has been set as the readability of stylesheets may be impacted. For example, in development, it might be useful for the output to indicate that the designer has intended to split declarations in a particular way.

@albeva
Copy link

albeva commented Jun 13, 2011

I think this should be part of new option to enable / disable optimizations. Another opportunity for optimizations is coalescing common properties:

/* for example: */
.foo { width: 10px; height: 10px; color: red; }
.bar { width: 10px; height: 10px; color: yellow; }
/* would become: */
.foo, .bar { width:10px; height:10px; }
.foo { color: red; }
.bar { color: yellow }

This kind of optimization is not safe however and therefore users should be able to test and see what side effects if any appear.

@Anahkiasen
Copy link

+1

@heygrady
Copy link

This may not be 100% related to this thread but I've seen every other marginally related ticket being closed and referred here.

Specifically for dealing with media queries it would be useful to use some sort of output buffering to stash some css rules for later inclusion. The issue is hinted at in the media queries blog article where trying to correct for media queries inline will result in a number of identical @media declarations that have different rules in them. Output buffering will solve this really well. Each buffer would be named and additive so each time it is invoked, more is appended to the end of it. Once a buffer is output it is flushed.

Buffering is a completely different usecase than a @mixin. Buffers would allow for the creation of a responsive grid plugin that expected specific buffers for specific @media blocks. Additionally it'd be useful for projects that want to create print styles using @print blocks. Currently the only way to manage this is to simply add your additional rules directly to the media queries which is effective but can make the code a little harder to track. Not having buffers also completely removes the capability of using canned media queries baked into a compass extension, making it harder to convert projects like 320 and up into SASS for easy re-use.

Here's a simple example:

.left-column {
  width: 300px; // for browsers that don't support media queries
  @buffer small-devices {
    & { width: 100%; }
  }
  @buffer medium-devices {
    & { width: 150px; }
  }
  @buffer large-devices {
    & { width: 300px; }
  }
}
.main-column {
  width: 660px; // for browsers that don't support media queries
  @buffer small-devices {
    & { width: 100%; }
  }
  @buffer medium-devices {
    & { width: 330px; }
  }
  @buffer large-devices {
    & { width: 660px; }
  }
}


@media only screen and (min-width: 0) {
  @output small-devices;
}
@media only screen and (min-width: 768px) {
  @output medium-devices;
}
@media only screen and (min-width: 992px) {
  @output large-devices;
}
  • buffers are output at the time that @output is called in the natural CSS order. So if you add to a buffer after it's been output, nothing happens.
  • you can easily add more to a buffer using the names.
  • it might be useful to clear a named buffer with something like @clean my-buffer;
  • I don't know if it's possible to use the & symbol in content blocks like in my example but it'd be really useful.
  • It would also be useful to use the bubbling feature similar to how @media works. Something like div { @buffer my-buffer { width: 100px; } width: 200px; }

@Anahkiasen
Copy link

Didn't think about an output buffer approach for media queries but I gotta say it doesn't look bad.

@JohanVandeplas
Copy link

+1

@pyronaur
Copy link

The buffer solution really looks good here...

@hotmeteor
Copy link

+1

@ogorzalka
Copy link

yeah +1 for the buffer !

@auchenberg
Copy link

+1

@cjcheshire
Copy link

  • 1 and + 1 for media query squishing!

@nathggns
Copy link

+1 for everything suggested!

@ghost
Copy link

ghost commented Jul 6, 2012

+1 for sure.

@simmo
Copy link

simmo commented Jul 24, 2012

+1 Great solution. Buffer would be a great feature.

@joshrives
Copy link

+1 for not repeating "@media screen and" a thousand times in my live file

@StanAngeloff
Copy link

I've been hacking on a @buffer support in Sass and progress can be seen on StanAngeloff/sass@nex3:master...StanAngeloff:feature/buffers The code is working at the moment, but lacks some features (see further down).

I plan on using this for my own projects, but if there is enough interest and the code is bug-free, I would be happy to submit a pull request for inclusion in core Sass.

The syntax I used is:

$device-size:  small;
$device-width: 640px;

body {
  color: white;
  @buffer #{$device-size}-screen {
    color: black;
  }
}

h1 {
  color: white;
  @buffer #{$device-size}-screen {
    color: black;

    .no-js & { color: red; }
  }
}

@media only screen and (max-width: #{$device-width}) {
  @flush #{$device-size}-screen;
}

Several features can be seen in action in the snippet above:

  • Rule bubbling
  • Interpolations
  • Parent selector (&) support
  • Converting between .scss <=> .sass using sass-convert

There is support for using @buffer within .sass files as well:

$device-size:  small
$device-width: 640px

body
  color: white
  #{$device-size}-screen ->
    color: black

h1
  color: white
  #{$device-size}-screen ->
    color: black

    .no-js &
      color: red

@media only screen and (max-width: #{$device-width})
  <- #{$device-size}-screen

What doesn't work / is missing

  • Error reporting and debugging has not been tested extensively
  • Buffer functions are not provided, e.g., buffer-exists(..) or buffer-empty(..)
  • This one is more for personal use -- ability to write buffers to files, i.e., generating media-specific files so main stylesheet can remain optimised for desktop screens

Try it out

  • Clone the repo

    $ git clone git://github.com/StanAngeloff/sass.git
  • Check out the feature/buffers branch

    $ cd sass
    $ git checkout feature/buffers
  • Build and install the gem

    $ gem build *.gemspec
    $ gem install --local *.gem

Feedback welcomed very much.

@simmo
Copy link

simmo commented Jul 30, 2012

@StanAngeloff Very interested by this, it would be great if this was implemented into Sass.

@GuillaumeSerrat
Copy link

+1

@nathggns
Copy link

Does anyone have any reasoning for why this wouldn't be possible?

@battaglr
Copy link

battaglr commented Aug 7, 2012

+1. Media queries are fundamentals these days, so would be really handy a more efficient way to manage the output to group them. Could be the one suggested by @heygrady —great idea BTW—, or another one, but would be nice to see some changes in the current approach.

@feross
Copy link

feross commented Aug 10, 2012

+1

@nex3
Copy link
Contributor

nex3 commented Aug 20, 2012

@StanAngeloff Please open a separate pull request for your @buffer stuff so we can discuss it further. It's not directly related to this feature request.

@battaglr
Copy link

@nex3 I think that @heygrady should open the separated pull request, since was his original idea and he probably can explain more in deep the matter. It's a really good idea the @buffer stuff. BTW: great work with the hacking @StanAngeloff.

@thepuzzlemaster
Copy link

+1. Would love to see something like this.

@heygrady
Copy link

@imbatta I didn't write any code, I was just offering an idea. I couldn't create a pull request without code. But thanks for thinking of me.

@battaglr
Copy link

@heygrady Oh, you're right, I kinda suck in some GitHub stuff yet; sorry for the misunderstood. Hope the @buffer thing end up implemented.

But coming back to the original feature request, I don't think it's a good idea. These kind of compilation will cause many headaches for sure. Anyway, if many people is interested, it could be an optional way to compile.

@pathaksubash
Copy link

+1

1 similar comment
@vieron
Copy link

vieron commented Sep 2, 2012

+1

@jaydenseric
Copy link

I like @lunelson's idea of applying @buffer to mixins: #116 (comment).

It should group mixin @flush dumps by matching mixin arguments. For example:

@mixin breakpoint($width) {
    @media (min-width: $width) {
        @content;
    }
}
@buffer breakpoint(700px) {
    h1 {
        color: red;
    }
}
@buffer breakpoint(700px) {
    p {
        color: blue;
    }
}
@buffer breakpoint(900px) {
    p {
        color: purple;
    }
}
@flush breakpoint;

Should output:

@media (min-width: 700px) {
    h1 {
        color: red;
    }
    p {
        color: blue;
    }
}
@media (min-width: 900px) {
    p {
        color: purple;
    }
}

@maranomynet
Copy link

+1 for @append

@append is a much cleaner, and more broadly applicable solution to the problem @buffer tries to solve.

(LESS has additive mixin declarations, which can be a real pain, but also proves incredibly powerful at times.)

@trabuccocampos
Copy link

+1

@shankarcabus
Copy link

+1 to use the css-condense logic.

@apipkin
Copy link

apipkin commented Dec 11, 2014

👍

@kevinSuttle
Copy link

Late to the party, but to me, an extension to Sass based on @stoyan's CSSShrink would be fantastic for intelligent compression. I do understand the challenges there though. Not trivial at all. http://cssshrink.com/velocity/

@esjosemartinez
Copy link

+1 for buffer

@Jakobud
Copy link

Jakobud commented Mar 10, 2015

For anyone who is using gulp, just use https://www.npmjs.com/package/gulp-combine-media-queries

It will combine your media queries together for you after compilation is complete. Works perfectly.

@mariendries
Copy link

+1 for buffer

@webbower
Copy link

+1 for buffer. Being able to nest related CSS and then control where it gets output seems like a generally useful tool. Something like:

@buffer("label") {
  // SCSS code
}

@flush("label");

Then...

// Mobile First BABY!!
.box {
  margin: 20px 10px;

  @buffer("tablet") {
    margin-left: 20px;
    margin-right: 20px;
  }

  @buffer("desktop") {
    margin-top: 40px;
    margin-bottom: 40px;
  }
}

// elsewhere

@media (min-width: 600px) {
  @flush("tablet"); // Outputs .box overrides and anything else in "tablet" buffer
}

@media (min-width: 900px) {
  @flush("desktop"); // Outputs .box overrides and anything else in "desktop" buffer
}

@juliankoehn
Copy link

+1 for buffer

@robsonsobral
Copy link

robsonsobral commented Oct 26, 2015

Hi!

I saw this discussion is really old, but I think there's something new to be considered: HTTP/2.

Soon, the good practice concerning requests will be "it depends". On HTTP/2 is better to split the CSS by media query and to reduce the file size. So, maybe it's better to keep every @media on its own file and to import or not on a screen widt basis; or we could @flush content buffered on another file... I don't know. I'm new to SASS. What I know is that the situation is changing from when this discussion began.

Thanks!

@musamamasood
Copy link

+1

@semisedlak
Copy link

+1

@matovas
Copy link

matovas commented Jan 23, 2016

hi,
I wrote an article about the targeting of styles in Sass
http://www.matov.pro/blog/adaptivity-targeting-styles
it is realy now

@Falven
Copy link

Falven commented Apr 9, 2016

+1

1 similar comment
@dswwsd
Copy link

dswwsd commented Jun 7, 2016

+1

@dmitry
Copy link

dmitry commented Jun 7, 2016

Please use emoji, instead of +1. Use comments for something really helpful for the issue.

@Herokid
Copy link

Herokid commented Jun 7, 2016

Ok, sorry for that.

El 7/6/16 a las 12:10, Dmitry Polushkin escribió:

Please use emoji, instead of +1.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#116 (comment), or
mute the thread
https://github.com/notifications/unsubscribe/ABPv4mkrDCIZf3Tni8KwSE3hvHq0tLe9ks5qJUOjgaJpZM4AAU9t.

David Saenz / david@herokidstudio.es mailto:david@herokidstudio.es /
www.herokidstudio.es http://www.herokidstudio.es / 93 320 90 90 ·
Pamplona 89, 3 · 08018 Barcelona

_Herokid Studio_™

@ghost
Copy link

ghost commented Nov 23, 2016

Use postcss.

https://github.com/hail2u/node-css-mqpacker
https://github.com/ben-eb/postcss-merge-rules

@nex3
Copy link
Contributor

nex3 commented Apr 4, 2018

These optimizations are no longer planned. Sass does what it can to eliminate extra whitespace and choose the smallest possible representation for values, but it's primary focus is being the best preprocessing language it can be rather than the best CSS compressor. Other tools exist that are focused on maximal optimization, and those are a better place for features like this.

In addition:

  • Combining namespaced selectors requires a lot of knowledge about the semantics of specific CSS property names, which is against Sass's design policy. Baking that knowledge into the language increases the amount of effort we as maintainers have to put in to keeping on top of the latest CSS specifications, and makes Sass more brittle to future CSS changes.

  • Ignoring overridden declarations is not generally safe. It's possible to use overridden declarations intentionally to provide fallback styles for browsers that don't support recent features. As above, we don't want to have to keep Sass up-to-date with which properties may or may not be safe to eliminate.

@nex3 nex3 closed this as completed Apr 4, 2018
@nex3 nex3 removed the planned We would like to add this feature at some point label Apr 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests